package com.jy.unkown;

import android.annotation.SuppressLint;
import android.os.Environment;
import android.util.Log;

import androidx.annotation.NonNull;


import com.jiayou.ziyou_ad.utils.MD5Util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.URL;
import java.util.EnumMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class MultiDownloadHelper {
    public static final String TAG = "DemoMultiDownloadWithProgressBar";
    private int threadCount = 0;
    private String downloadFilePath = "";

    private String destFileDir;
    private String destFileName;


    public MultiDownloadHelper setDestFileDir(String destFileDir) {
        this.destFileDir = destFileDir;
        return this;
    }

    public MultiDownloadHelper setDestFileName(String destFileName) {
        this.destFileName = destFileName;
        return this;
    }

    public MultiDownloadHelper(int threadCount, String url) {
        this.threadCount = threadCount;
        this.downloadFilePath = url;
    }

    private enum DownLoadThreadInfor {
        threadLength, startPosition
    }

    private EnumMap<DownLoadThreadInfor, Object> calcStartPosition(long fileLength, int threadNo) {
        int threadlength = (int) fileLength % threadCount == 0 ? (int) fileLength / threadCount : (int) fileLength + 1;
        int startPosition = threadNo * threadlength;
        EnumMap<DownLoadThreadInfor, Object> downloadThreadInfor = new EnumMap<DownLoadThreadInfor, Object>(DownLoadThreadInfor.class);
        downloadThreadInfor.put(DownLoadThreadInfor.threadLength, threadlength);
        downloadThreadInfor.put(DownLoadThreadInfor.startPosition, startPosition);
        return downloadThreadInfor;
    }

    @SuppressLint("LongLogTag")
    private String generateTempFile(String filePath, long fileLength) throws Exception {
        RandomAccessFile file = null;
        try {
            File dir = new File(destFileDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }


            String fileName = new File(dir, destFileName).getAbsolutePath();
            Log.d(TAG, ">>>>>>写入->" + fileName);
            file = new RandomAccessFile(fileName, "rwd");
            file.setLength(fileLength);
            return fileName;
        } catch (Exception e) {
            throw new Exception("GenerateTempFile error: " + e.getMessage(), e);
        } finally {
            try {
                file.close();
            } catch (Exception e) {
            }
        }

    }

    private class DownLoadThread extends Thread {
        private int threadId;
        private int startPosition;
        private RandomAccessFile threadFile;
        private int threadLength;
        private String downloadFilePath;
        private DownloadListener downloadListener;
        private int totalSize = 0;

        public DownLoadThread(int threadId, int startPosition,
                              RandomAccessFile threadFile, int threadLength, String downloadFilePath, DownloadListener downloadListener,
                              int totalSize) {
            this.threadId = threadId;
            this.startPosition = startPosition;
            this.threadFile = threadFile;
            this.threadLength = threadLength;
            this.downloadFilePath = downloadFilePath;
            this.downloadListener = downloadListener;
            this.totalSize = totalSize;
        }

        @SuppressLint("LongLogTag")
        public void run() {
            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder()
                    .url(downloadFilePath)//请求接口，如果需要传参拼接到接口后面
                    .build(); //创建Request对象
            Log.d(TAG, ">>>>>>线程" + (threadId + 1) + "开始下载...");
            Call call = client.newCall(request);
            //异步请求
            call.enqueue(new Callback() {
                //失败的请求
                @Override
                public void onFailure(@NonNull Call call, @NonNull IOException e) {
                    Log.e(TAG, ">>>>>>下载进程加载->" + downloadFilePath + " error:" + e.getMessage(), e);
                }

                //结束的回调
                @Override
                public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                    Log.d(TAG, ">>>>>>连接->" + downloadFilePath + " 己经连接，进入下载...");
                    InputStream is = null;
                    try {
                        if (200 == response.code()) {
                            Log.d(TAG, ">>>>>>response.code()==" + response.code());
                            Log.d(TAG, ">>>>>>response.message()==" + response.message());
                            is = response.body().byteStream();
                            byte[] buffer = new byte[1024];
                            int len = -1;
                            int length = 0;
                            while (length < threadLength && (len = is.read(buffer)) != -1) {
                                threadFile.write(buffer, 0, len);
                                //计算累计下载的长度
//                                length += len;
                                downloadListener.onDownload(len, totalSize);
                            }
                            Log.d(TAG, ">>>>>>线程" + (threadId + 1) + "已下载完成");
                        }
                    } catch (Exception e) {
                        Log.e(TAG, ">>>>>>线程:" + threadId + " 下载出错: " + e.getMessage(), e);
                    } finally {
                        try {
                            threadFile.close();
                        } catch (Exception e) {
                        }
                        try {
                            is.close();
                            ;
                        } catch (Exception e) {
                        }
                    }

                }
            });

        }
    }

    @SuppressLint("LongLogTag")
    private void download(DownloadListener downloadListener) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(downloadFilePath)//请求接口，如果需要传参拼接到接口后面
                .build(); //创建Request对象
        try {
            Call call = client.newCall(request);
            //异步请求
            call.enqueue(new Callback() {
                //失败的请求
                @SuppressLint("LongLogTag")
                @Override
                public void onFailure(@NonNull Call call, @NonNull IOException e) {
                    Log.e(TAG, ">>>>>>加载->" + downloadFilePath + " error:" + e.getMessage(), e);
                    downloadListener.downloadErr(downloadFilePath, e);
                }

                //结束的回调
                @SuppressLint("LongLogTag")
                @Override
                public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                    //响应码可能是404也可能是200都会走这个方法
                    Log.i(TAG, ">>>>>>the response code is: " + response.code());
                    if (200 == response.code()) {
                        Log.d(TAG, ">>>>>>response.code()==" + response.code());
                        Log.d(TAG, ">>>>>>response.message()==" + response.message());
                        try {
                            long size = response.body().contentLength();
                            Log.d(TAG, ">>>>>>file length->" + size);
                            for (int i = 0; i < threadCount; i++) {
                                EnumMap<DownLoadThreadInfor, Object> downLoadThreadInforObjectEnumMap = new EnumMap<DownLoadThreadInfor, Object>(DownLoadThreadInfor.class);
                                downLoadThreadInforObjectEnumMap = calcStartPosition(size, i);
                                String threadFileName = generateTempFile(downloadFilePath, size);
                                int startPosition = (int) downLoadThreadInforObjectEnumMap.get(DownLoadThreadInfor.startPosition);
                                int threadLength = (int) downLoadThreadInforObjectEnumMap.get(DownLoadThreadInfor.threadLength);
                                RandomAccessFile threadFile = new RandomAccessFile(threadFileName, "rwd");
                                threadFile.seek(startPosition);
                                new DownLoadThread(i, startPosition, threadFile, threadLength, downloadFilePath, downloadListener, (int) size).start();
                                Log.d(TAG, ">>>>>>start thread: " + i + 1 + " start position->" + startPosition);
                            }
                        } catch (Exception e) {
                            Log.e(TAG, ">>>>>>get remote file size error: " + e.getMessage(), e);
                        }
                    }
                }
            });
        } catch (Exception e) {
            Log.e(TAG, ">>>>>>open connection to path->" + downloadFilePath + "\nerror: " + e.getMessage(), e);
        }
    }


    String msg = "asd";
    long downSize=0;
    public void startDownload(DownloadUtil.OnDownloadListener onDownloadListener) {
        download(new DownloadListener() {
            @Override
            public void onDownload(int size, int totalSize) {
                synchronized (msg) {
                    downSize+=size;
                    long progress = downSize * 100 / totalSize;
                    onDownloadListener.onDownloading(downloadFilePath, (int)progress);
                    if (size == totalSize) {
                        File dir = new File(destFileDir);
                        if (!dir.exists()) {
                            dir.mkdirs();
                        }
                        onDownloadListener.onDownloadSuccess(downloadFilePath, new File(dir, destFileName));
                    }
                }
            }

            @Override
            public void downloadErr(String url, Exception e) {
                onDownloadListener.onDownloadFailed(url, e);
            }
        });


    }


}